package net.lengwang.iot.middleware.packet.request;

import net.lengwang.iot.middleware.packet.PacketType;
import net.lengwang.iot.middleware.packet.ParsedPacket;
import net.lengwang.iot.middleware.packet.request.*;

//parsedPacket
public class PacketParser {

    // 解析通用报文数据包，返回解析后的信息
    public static ParsedPacket parsePacket(byte[] packet) throws Exception {
        // 验证数据包的最小长度
        if (packet.length < 10) {
            throw new Exception("数据包长度过小，不符合最低长度要求");
        }
        ParsedPacket parsedPacket = new ParsedPacket();
        // System.out.println("(1)处理前的 ParsedPacket: " + parsedPacket);

        // conver to bytesToHex(packet)
        String hexPacket = bytesToHex(packet);
        // 将十六进制字符串转换为大写
        hexPacket = hexPacket.toUpperCase();
        parsedPacket.setRawData(packet);
        parsedPacket.setParsedData(hexPacket);

        // hexPacket.substring(6, 8)判断类型
        String packetType = hexPacket.substring(6, 8);
        // set rawData

        switch (packetType) {
            case PacketType.BEBE_GATEWAY_HANDSHAKE:
                parsedPacket = HandshakePacketParser.parsePacket(parsedPacket);
                break;
            case PacketType.BEBE_GATEWAY_TIME_SYNC:
                parsedPacket = TimeSyncPacketParser.parsePacket(parsedPacket);
                break;
            // BEBE_GATEWAY_STATUS_REPORT
            case PacketType.BEBE_GATEWAY_STATUS_REPORT:
                parsedPacket = StatusReportPacketParser.parsePacket(parsedPacket);
                break;
            // todo 添加其他类型解析
            default:
                // 处理未知类型
                break;
        }

        // }
        // 可以扩展其他命令类型的解析

        return parsedPacket;
    }

    // CRC 校验（简单示例）
    private static boolean verifyCRC(String hexPacket) {
        int length = hexPacket.length();
        // 假设最后4字节是CRC和结束位
        String dataWithoutCrc = hexPacket.substring(0, length - 4);
        String crcBytes = hexPacket.substring(length - 4, length - 2);
        // 计算并校验CRC
        // CRC具体的算法需要根据文档规定的计算方法实现
        return true; // TODO: 换为实际的CRC校验
    }

    // 解析授时数据
    private static void parseTimeSyncData(String hexPacket, ParsedPacket parsedPacket) {
        // 例如，解析授时数据中的时间信息
        String time = hexPacket.substring(11, 17);
        parsedPacket.setTime(time);
    }

    // 解析网关状态数据
    private static void parseStatusData(String hexPacket, ParsedPacket parsedPacket) {
        // 例如，解析网关状态中的电压和信号度
        String voltageBytes = hexPacket.substring(19, 21);
        double voltage = parseVoltage(voltageBytes);
        parsedPacket.setVoltage(voltage);

        String signalStrength = hexPacket.substring(32, 34);
        parsedPacket.setSignalStrength(signalStrength);
    }

    // 电压解析方法
    private static double parseVoltage(String voltageBytes) {
        int rawValue = Integer.parseInt(voltageBytes, 16);
        return rawValue / 1000.0;
    }

    // bytesToHex
    public static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(b & 0xFF);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static int parseSequenceNumber(byte[] data) {
        if (data.length < 2) {
            throw new IllegalArgumentException("数据长度不足以解析序列号");
        }
        return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
    }

    public static String extractDeviceId(byte[] data) {
        if (data.length < 8) {
            throw new IllegalArgumentException("数据长度不足以提取设备ID");
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 8; i++) {
            sb.append(String.format("%02X", data[i]));
        }
        return sb.toString();
    }

    public static String bcdToTimeString(byte[] bcdTime) {
        if (bcdTime.length != 6) {
            throw new IllegalArgumentException("BCD时间数据长度应为6字节");
        }
        StringBuilder sb = new StringBuilder();
        for (byte b : bcdTime) {
            sb.append(String.format("%02X", b));
        }
        return sb.substring(0, 4) + "-" + sb.substring(4, 6) + "-" + sb.substring(6, 8) + " " +
                sb.substring(8, 10) + ":" + sb.substring(10, 12);
    }

    public static byte[] encodeBCDTime(int year, int month, int day, int hour, int minute, int second) {
        byte[] bcdTime = new byte[6];
        bcdTime[0] = (byte) ((year / 100 << 4) | (year % 100));
        bcdTime[1] = (byte) ((month << 4) | day);
        bcdTime[2] = (byte) ((hour << 4) | minute);
        bcdTime[3] = (byte) (second << 4);
        return bcdTime;
    }

    private static String getPacketTypeByCommand(String command) {
        for (String type : PacketType.getAllTypes()) {
            if (type.equals(command)) {
                return type;
            }
        }
        return PacketType.UNKNOWN;
    }

}
